这两个代码片段有什么区别?
使用type():
type()
import types if type(a) is types.DictType: do_something() if type(b) in types.StringTypes: do_something_else()
使用isinstance():
isinstance()
if isinstance(a, dict): do_something() if isinstance(b, str) or isinstance(b, unicode): do_something_else()
总结其他(已经很好!)答案的内容,isinstance迎合继承(派生类 的 实例也是基类的实例),同时检查type不相等(它需要类型的标识并拒绝实例子类型,AKA 子类)。
isinstance
type
通常,在 Python 中,您当然希望您的代码支持继承(由于继承非常方便,因此阻止使用您的代码使用它会很糟糕!),所以isinstance比检查types 的身份更糟糕,因为它无缝支持遗产。
这不是isinstance很好 , 请注意,这比检查类型的 相等 性要好。正常的,Pythonic,首选的解决方案几乎总是“鸭子类型”:尝试使用参数 ,就好像 它是某种所需类型一样,在try/except语句中执行它,以捕获如果参数不是事实可能出现的所有异常类型(或任何其他类型很好地模仿它;-),并在except子句中尝试其他内容(使用参数“好像”它是其他类型)。
try
except
basestring 然而,它是 一个非常特殊的情况——内置类型,它的存在 只是 为了让你使用isinstance(str和unicode子类basestring)。字符串是序列(您可以对它们进行循环、索引、切片,…),但您通常希望将它们视为“标量”类型——处理所有类型有点不方便(但相当频繁的用例)一种方式的字符串(可能还有其他标量类型,即不能循环的类型),另一种方式的所有容器(列表,集合,字典,…),并且basestring可以isinstance帮助您做到这一点 - 他的整体结构这个成语是这样的:
basestring
str
unicode
if isinstance(x, basestring) return treatasscalar(x) try: return treatasiter(iter(x)) except TypeError: return treatasscalar(x)
你可以说这basestring是一个 抽象基类 (“ABC”)——它没有为子类提供具体的功能,而是作为一个“标记”存在,主要用于isinstance. 这个概念在 Python 中显然是一个不断增长的概念,因为PEP 3119引入了它的泛化,被接受并从 Python 2.6 和 3.0 开始实施。
PEP 明确指出,虽然 ABC 通常可以替代鸭式打字,但这样做通常没有太大的压力(请参阅此处)。然而,在最近的 Python 版本中实现的 ABC 确实提供了额外的好处:isinstance(and issubclass) 现在不仅仅意味着“派生类的[一个实例]”(特别是,任何类都可以在 ABC 中“注册”,以便它将显示为子类,其实例为 ABC 的实例);和 ABC 还可以通过模板方法设计模式应用程序以非常自然的方式为实际子类提供额外的便利(有关 TM DP 的更多信息,请参见此处和此处[[part II]],一般而言,特别是在 Python 中,独立于 ABC) .
issubclass
有关 Python 2.6 中提供的 ABC 支持的底层机制,请参见此处;对于他们的 3.1 版本,非常相似,请参见此处。在这两个版本中,标准库模块集合(即 3.1 版本或非常相似的 2.6 版本,请参见此处)提供了几个有用的 ABC。
出于这个答案的目的,保留关于 ABC 的关键(除了可以说是 TM DP 功能更自然的位置,与诸如UserDict.DictMixin之类的 mixin 类的经典 Python 替代方案相比)是它们使isinstance(和issubclass)更多与以前(在 2.5 及之前的版本中)相比,更有吸引力和普遍(在 Python 2.6 及以后版本中),因此,相比之下,在最近的 Python 版本中,检查类型相等性比以前更糟糕。